package com.yexiao.cofe.business.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yexiao.cofe.business.mapper.*;
import com.yexiao.cofe.business.pojo.*;
import com.yexiao.cofe.business.service.ProductService;
import com.yexiao.cofe.common.exception.BusinessException;
import com.yexiao.cofe.constant.ProductConstant;
import com.yexiao.core.util.JSONUtil;
import com.yexiao.core.util.StrUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

@Service
public class ProductServiceImpl implements ProductService {

    @Resource
    private ProductMapper productMapper;
    @Resource
    private CategoryMapper categoryMapper;
    @Resource
    private StoreProductMapper storeProductMapper;
    @Resource
    private TemplateParamMapper templateParamMapper;
    @Resource
    private ParamItemMapper paramItemMapper;
    @Resource
    private ParamValueMapper paramValueMapper;

    @Override
    public void addProduct(JSONObject param) {
        String name = JSONUtil.checkAndGetStr(param, "name");
        String description = JSONUtil.getStr(param, "description");
        Integer categoryId = JSONUtil.checkAndGetInt(param, "categoryId");
        BigDecimal basePrice = new BigDecimal(JSONUtil.checkAndGetStr(param, "basePrice"));
        List<String> imageList = JSONUtil.getList(param, String.class, "imageList");
        Integer sort = JSONUtil.getIntDef(param, 0, "sort");

        // 校验类别
        Category category = categoryMapper.selectById(categoryId);
        if(category == null) {
            throw new BusinessException("类别不存在");
        }

        Product product = new Product()
                .setProductId(generateProductId())
                .setName(name)
                .setDescription(description)
                .setCategoryId(categoryId)
                .setBasePrice(basePrice)
                .setImage(concatImage(imageList))
                .setIsDel(ProductConstant.Product_Not_Del)
                .setSort(sort); // 默认排序权重

        // 插入数据库
        productMapper.insert(product);
    }

    private String concatImage(List<String> imageList) {
        StringBuilder sb = new StringBuilder();
        for (String s : imageList) {
            sb.append(s);
            sb.append(",");
        }
        if(StrUtil.isNotEmpty(sb.toString())) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    @Override
    public void updateProduct(JSONObject param) {
        Integer productId = JSONUtil.checkAndGetInt(param, "productId");
        String name = JSONUtil.getStr(param, "name");
        String description = JSONUtil.getStr(param, "description");
        Integer categoryId = JSONUtil.getInt(param, "categoryId");
        String basePrice = JSONUtil.getStr(param, "basePrice");
        List<String> imageList = JSONUtil.getList(param, String.class, "imageList");
        Integer sort = JSONUtil.getInt(param, "sort");

        Product product = productMapper.getProduct(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }

        if(categoryId != product.getCategoryId() && categoryMapper.selectById(categoryId) == null) {
            throw new BusinessException("类型不存在");
        }

        productMapper.modifyProduct(productId, name, description, categoryId, basePrice, concatImage(imageList), sort);
    }

    @Override
    public void deleteProduct(JSONObject param) {
        Integer productId = JSONUtil.checkAndGetInt(param, "id");
        productMapper.delByProductId(productId);
    }

    @Override
    public JSONObject listProduct(JSONObject param, String token) {
        Integer pageNum = JSONUtil.checkAndGetInt(param, "pageNum");
        Integer pageSize = JSONUtil.checkAndGetInt(param, "pageSize");
        String name = JSONUtil.getStr(param, "name");

        PageHelper.startPage(pageNum, pageSize);
        List<Product> productList = productMapper.listProduct(name);
        PageInfo<Product> productPageInfo = new PageInfo<>(productList);

        List<JSONObject> msgList = new ArrayList<>();
        for (Product product : productList) {
            msgList.add(Product.getBaseMsg(product));
        }

        return JSONUtil.of(
                "pageNum", productPageInfo.getPageNum(),
                "nextPage", productPageInfo.getNextPage(),
                "pageSize", productPageInfo.getPageSize(),
                "total", productPageInfo.getTotal(),
                "list", msgList
        );
    }

    @Override
    public JSONObject detail(JSONObject param) {
        Integer productId = JSONUtil.checkAndGetInt(param, "productId");
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }

        return Product.getBaseMsg(product);
    }

    @Override
    public JSONObject detailWithParam(JSONObject param) {
        String storeId = JSONUtil.checkAndGetStr(param, "storeId");
        Integer productId = JSONUtil.checkAndGetInt(param, "productId");
        Product product = productMapper.selectById(productId);
        if (product == null) {
            throw new BusinessException("商品不存在");
        }
        JSONObject baseMsg = Product.getBaseMsg(product);
        baseMsg.put("paramList", getParamByStoreIdAndProductId(storeId, productId));
        return baseMsg;
    }

    @Override
    public void modifyPrice(JSONObject param) {
        String storeId = JSONUtil.checkAndGetStr(param, "storeId");
        String price = JSONUtil.checkAndGetStr(param, "price");
        Integer productId = JSONUtil.checkAndGetInt(param, "productId");

        storeProductMapper.modifyPrice(storeId, productId, new BigDecimal(price).doubleValue());
    }

    @Override
    public void operationProduct(JSONObject param) {
        String storeId = JSONUtil.checkAndGetStr(param, "storeId");
        Integer productId = JSONUtil.checkAndGetInt(param, "productId");
        Integer op = JSONUtil.checkAndGetInt(param, "op");
        if(op < 0 || op > 2) {
            throw new BusinessException("操作异常");
        }

        storeProductMapper.opProductStatus(storeId, productId, op);
    }

    private Integer generateProductId() {
        return (int) (System.currentTimeMillis() % 1000000);
    }

    /**
     * 根据门店id和产品id获取参数
     */
    private List<JSONObject> getParamByStoreIdAndProductId(String storeId, Integer productId) {
        StoreProduct storeProduct = storeProductMapper.selectByStoreIdAndProductId(storeId, productId);
        if(storeProduct == null) {
            throw new BusinessException("未查询到商品");
        }

        return getParamByTemplateId(storeProduct.getParamTemplateId());
    }

    /**
     * 根据模板id获取绑定参数
     */
    private List<JSONObject> getParamByTemplateId(Integer templateId) {
        List<TemplateParam> templateParamList = templateParamMapper.selectByTemplateId(templateId);
        List<ParamItem> paramItemList = paramItemMapper.listAll();
        List<ParamValue> paramValueList = paramValueMapper.listAll();

        List<JSONObject> res = new ArrayList<>();
        for (ParamItem paramItem : paramItemList) {
            JSONObject itemMsg = ParamItem.getParamItemBaseMsg(paramItem);

            List<JSONObject> valueList = new ArrayList<>();
            for (TemplateParam templateParam : templateParamList) {
                if(templateParam.getParamItemId() != paramItem.getId()) {
                    continue;
                }

                for (ParamValue paramValue : paramValueList) {
                    if(paramValue.getId() == templateParam.getParamValueId()) {
                        valueList.add(ParamValue.getBaseMsg(paramValue));
                        break;
                    }
                }
            }

            if(CollectionUtil.isEmpty(valueList)) {
                itemMsg.put("valueList", valueList);
                res.add(itemMsg);
            }
        }

        return res;
    }
}
